home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / source / main / parse.c < prev    next >
Text File  |  1994-02-20  |  46KB  |  1,432 lines

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1992,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. ****************************************************************/
  13.  
  14. #ifdef MPW
  15. #pragma segment 4
  16. #endif
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20.  
  21. #include "TelnetHeader.h"
  22. #include "parse.h"                // For our #defines
  23. #include "wind.h"                /* For WindRec structure */
  24. #include "network.proto.h"                /* For net functions */
  25. #include "debug.h"                /* For putln proto */
  26. #include "vgtek.proto.h"
  27. #include "vsdata.h"
  28. #include "vsinterf.proto.h"
  29. #include "maclook.proto.h"
  30. #include "tekrgmac.proto.h"
  31. #include "menuseg.proto.h"
  32.  
  33. #include "vr.h"
  34. #include "vr.proto.h"
  35. #include "encrypt.proto.h"
  36. #include "kerberos.proto.h"
  37. #include "wdefpatch.proto.h"
  38.  
  39. //#define    OPTS_DEBUG
  40. #ifdef    OPTS_DEBUG
  41. #define    opts_debug_print(x)    putln(x)    
  42. #include "optsdebug.h"
  43. #else
  44. #define    opts_debug_print(x)
  45. #endif
  46.  
  47. #define    SEND_NOSUPPORT_ON_SLC_INIT    1
  48.  
  49. extern short     scrn;
  50. extern WindRec    *screens;
  51.  
  52. #include "parse.proto.h"
  53.  
  54. /*********************************************************************/
  55. /*  parse
  56. *   look at the string which has just come in from outside and
  57. *   check for special sequences that we are interested in.
  58. *
  59. *   Tries to pass through routine strings immediately, waiting for special
  60. *   characters ESC and 255 to change modes.
  61. */
  62.  
  63. #ifdef notdef
  64. void parse (struct WindRec *tw, unsigned char *st, short cnt)
  65. {
  66.     short    j, l;
  67.     unsigned char *cp, ebuf[256];
  68.  
  69.     if (tw && tw->decrypt_input) {
  70.         while (cnt > 0) {
  71.             l = j = ((cnt > sizeof(ebuf))? sizeof(ebuf) : cnt);
  72.             cp = ebuf;
  73.             while (j-- > 0)
  74.                 *cp++ = (*tw->decrypt_input)(tw, (int)(*st++));
  75.             parse2(tw, ebuf, l);        
  76.             cnt -= l;
  77.         }        
  78.     } else {
  79.         parse2(tw, st, cnt);
  80.     }
  81. }
  82. #endif
  83.  
  84. void parse (struct WindRec *tw, unsigned char *st, short cnt)
  85. {
  86.     short i,temptw;
  87.     unsigned char *mark,*orig;
  88. #ifdef OPTS_DEBUG
  89.     char munger[255]; 
  90. #endif
  91.     unsigned char *cp;
  92.     char nullbuf[] = {AUTH_NULL, AUTH_CLIENT_TO_SERVER|AUTH_HOW_ONE_WAY};
  93.  
  94.     orig = st;                /* remember beginning point */
  95.     mark = st + cnt;        /* set to end of input string */
  96. /*
  97. * raw mode for debugging, passes through escape sequences and other
  98. * special characters as <27> symbols
  99. */
  100.     if (tw->termstate == DUMBTYPE)
  101.         {
  102.         for (i=0; i < cnt; i++,st++)            /* put on screen raw */
  103.             if (*st == 27 || *st > 126 && !(tw->ftpstate && gFTPServerPrefs->DoISOtranslation))
  104.                 {
  105.                 sprintf((char *)tw->parsedat,"<%d>",*st);
  106.                 VSwrite(tw->vs,(char *)tw->parsedat,strlen((char *)tw->parsedat));    /* send to virtual screen */
  107.                 }
  108.             else
  109.                 VSwrite(tw->vs,(char *) st,1);        /* BYU LSC */
  110.         }
  111.     else
  112.         {
  113.  
  114. /*
  115. *  traverse string, looking for any special characters which indicate that
  116. *  we need to change modes.
  117. */
  118.     while (st < mark) 
  119.         {
  120.         switch (tw->telstate)
  121.             {
  122.             case GS:
  123.             case ESCFOUND:
  124.                 if (tw->tektype >= 0) {    /* we'll allow the TEK */
  125.                     if ((*st == 12) || (tw->telstate == GS)) {    /* esc-FF */
  126.                         if ((*st == 12) && 
  127.                             ((tw->termstate == VTEKTYPE) || (!tw->tekclear))) {
  128.                             if (tw->termstate == VTEKTYPE)
  129.                                 putln("Entering Tek mode");
  130.                             else if (tw->curgraph > -1)
  131.                                 detachGraphics(tw->curgraph);
  132.  
  133.                             if (tw->curgraph <=  -1) {        // No current TEK window
  134.                                 temptw = VGnewwin(1,tw->vs);
  135.  
  136.                                 if (temptw > -1) {
  137.                                     Str255    scratchPstring;
  138.                                     
  139.                                     tw->curgraph = temptw;
  140.     
  141.                                     VGgiveinfo(temptw);
  142.                                     GetWTitle(tw->wind, scratchPstring);
  143.                                     PtoCstr(scratchPstring);
  144.                                     RGattach(temptw,tw->vs,(char *)scratchPstring, tw->tektype);
  145.                                 }
  146.                                 else
  147.                                     tw->telstate = STNORM;  // Can't create TEK window
  148.                             }
  149.  
  150.                             if (tw->telstate != STNORM)
  151.                                 tw->termstate = TEKTYPE;
  152.                         }
  153.  
  154.                         if (tw->telstate == GS) {
  155.                             st++;
  156.                             VGwrite(tw->curgraph,"\035",1);
  157.                         }
  158.                         else if (tw->telstate != STNORM)
  159.                             VGwrite(tw->curgraph,"\037\033\014",3);
  160.  
  161.                         tw->telstate = STNORM;
  162.                         break;
  163.                     } // FF or GS
  164.                 } // tw->tektype >= 0
  165.     
  166.                 if (*st == '^')    {            /* ESC- ^ */
  167.                     tw->termstate = RASTYPE;
  168.                     tw->telstate = STNORM;
  169.                     VRwrite("\033^",2);        /* Put it through */
  170.                     orig = ++st;
  171.                     break;
  172.                 }
  173.                 
  174.                 if (tw->termstate == TEKTYPE)
  175.                     VGwrite(tw->curgraph,"\033",1);
  176.                 else if (tw->termstate  == RASTYPE)
  177.                     VRwrite("\033",1);
  178.                 else
  179.                     VSwrite(tw->vs,"\033",1);    /* send the missing ESC */
  180.                 tw->telstate = STNORM;
  181.                 break;
  182.  
  183.  
  184. /*------------------------------------------------------------------------------*
  185.  *     IACFOUND:  This is the start of the Telnet option negotiation.  If Telnet    *
  186.  *    gets an IAC character, then negotiation data follows, and is ready to be    *
  187.  *     parsed.                                                                     *
  188.  *------------------------------------------------------------------------------*/
  189.             case IACFOUND:         /* telnet option negotiation- START */
  190.                 if (*st == 255) {        /* real data = 255 */
  191.                     orig = st;            // MP: translation mod (break will make it miss
  192.                                         // this assignment later on in the case, Jim!)
  193.                     st++;                /* real 255 will get sent */
  194.                     tw->telstate = STNORM;
  195.                     break;
  196.                 }
  197.                 if ( 239 < *st ) {
  198.                     tw->telstate = *st;        /* by what the option is */
  199.                     st++;
  200.                     break;
  201.                 }
  202.                 tw->telstate = STNORM;
  203.                 orig=st;
  204.                 break;
  205.  
  206.  
  207.             case TEL_EOF:        /* BYU LSC */
  208. #ifdef OPTS_DEBUG
  209.                 sprintf(munger,"RECV: %s",telstates[tw->telstate - TEL_SE]);
  210.                 opts_debug_print(munger); 
  211. #endif
  212.                 orig=st;
  213.                 tw->telstate=STNORM;
  214.                 break;
  215.  
  216.             case TEL_EL:                /* thanx Quincey!!! */
  217.             case TEL_EC:
  218.             case TEL_AYT:
  219.             case TEL_AO:
  220.             case TEL_IP:
  221.             case TEL_BREAK:
  222.             case TEL_DM:
  223.             case TEL_NOP:
  224.             case TEL_SE:
  225. #ifdef OPTS_DEBUG
  226.                 sprintf(munger,"RECV: %s",telstates[tw->telstate - TEL_SE]);
  227.                 opts_debug_print(munger); 
  228. #endif
  229.                 tw->telstate = STNORM;
  230.                 orig=st;
  231.  
  232.  
  233.             case TEL_GA:
  234.                 orig=st;
  235.                 tw->telstate = STNORM;
  236.                 break;
  237.  
  238.  
  239.  
  240. /*------------------------------------------------------------------------------*
  241.  *     Negotiate DOTEL:  sent by the server whenever it wants the client to do     *
  242.  *    an option                                                                    *
  243.  *------------------------------------------------------------------------------*/
  244.             case TEL_DOTEL:
  245. #ifdef OPTS_DEBUG
  246.                 sprintf(munger,"RECV: %s %s",telstates[tw->telstate-TEL_SE],teloptions[*st]);
  247.                 opts_debug_print(munger); 
  248. #endif
  249.                 switch( *st) 
  250.                     {
  251.                     case  N_SGA:        /* Sure we'll supress GA */
  252.                         if (!tw->Isga) {
  253.                             tw->Isga=1;
  254.                             sprintf((char *)tw->parsedat,"%c%c%c",255,TEL_WILLTEL,*st);
  255.                             netpush(tw->port);
  256.                             netwrite(tw->port,tw->parsedat,3);
  257.                             }
  258. #ifdef OPTS_DEBUG
  259.                         sprintf(munger,"SENT: WILL %s",teloptions[*st]);
  260.                         opts_debug_print(munger); 
  261. #endif
  262.                         tw->telstate = STNORM;
  263.                         orig = ++st;
  264.                         break;
  265.                     
  266.                     case N_TERMTYP:        /* And we'll even tell you about ourselves */
  267.                         if (!tw->Ittype) {
  268.                             tw->Ittype=1;
  269.                             sprintf((char *)tw->parsedat,"%c%c%c",255,TEL_WILLTEL,*st);
  270.                             netpush(tw->port);
  271.                             netwrite(tw->port,tw->parsedat,3);
  272.                             }
  273. #ifdef OPTS_DEBUG
  274.                         sprintf(munger,"SENT: WILL %s",teloptions[*st]);
  275.                         opts_debug_print(munger); 
  276. #endif
  277.                         tw->telstate = STNORM;
  278.                         orig = ++st;
  279.                         break;
  280.  
  281.                     case  N_NAWS:            /* NCSA: sure, I like changing the window size! */
  282.                         tw->naws =1;        /* NCSA: this session is now NAWS */
  283.                         sprintf((char *)tw->parsedat,"%c%c%c",255,TEL_WILLTEL,*st);        /* NCSA: reply, we will to NAWS */
  284.                         netpush(tw->port);                                /* NCSA */
  285.                         netwrite(tw->port,tw->parsedat,3);                /* NCSA: send it out */
  286. #ifdef OPTS_DEBUG
  287.                         sprintf(munger,"SENT: WILL %s",teloptions[*st]);
  288.                         opts_debug_print(munger); 
  289. #endif
  290.                         SendNAWSinfo(tw, tw->width, tw->rows);
  291. //                        sprintf((char *)tw->parsedat,"%c%c%c%c%c%c%c%c%c",IAC,TEL_SB,    /* BYU 2.4.16 */
  292. //                            N_NAWS,(char)0,(unsigned char)tw->width,        /* BYU 2.4.16 */
  293. //                            (char)0,(unsigned char)tw->rows,IAC,TEL_SE);    /* BYU 2.4.16 */
  294. //                        netpush(tw->port);                                /* BYU 2.4.16 */
  295. //                        netwrite(tw->port,tw->parsedat,9);                    /* BYU 2.4.16 */
  296. #ifdef OPTS_DEBUG
  297.                         opts_debug_print("SENT: IAC TEL_SB N_NAWS <data> IAC TEL_SE"); 
  298. #endif
  299.  
  300.                         tw->telstate = STNORM;                            /* NCSA */
  301.                         orig = ++st;                                    /* NCSA */
  302.                         break;                                            /* NCSA */
  303.  
  304.                     case N_LINEMODE:  /* Sure I'll do line mode... */
  305.                         if (tw->lineAllow)  {
  306.                             sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_WILLTEL,*st++);
  307.                             netwrite(tw->port,tw->parsedat,3);
  308. #ifdef OPTS_DEBUG
  309.                             sprintf(munger,"SENT: WILL %s",teloptions[*st]);
  310.                             opts_debug_print(munger); 
  311. #endif
  312.                             sprintf((char *)tw->parsedat,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  313.                             netwrite(tw->port,tw->parsedat,4);
  314. #ifdef OPTS_DEBUG
  315.                             opts_debug_print("SENT: IAC SB LINEMODE SLC");
  316. #endif    
  317.                             for (i=1; i<= SLC_MAX; i++){
  318.                                 if (tw->slc[i]==-1) {
  319. #ifdef    SEND_NOSUPPORT_ON_SLC_INIT
  320.                                     sprintf((char *)tw->parsedat,"%c%c%c",i,SLC_NOSUPPORT,0);
  321. #ifdef OPTS_DEBUG
  322.                                     sprintf(munger,"     %s NO_SUPPORT 0",LMoptions[i]);
  323. #endif
  324. #endif
  325.                                     }
  326.                                 else
  327.                                     {
  328.                                     sprintf((char *)tw->parsedat,"%c%c%c",i,SLC_CANTCHANGE,(char)tw->slc[i]);
  329.  
  330. #ifdef OPTS_DEBUG
  331.                                     sprintf(munger,"     %s CANTCHANGE %i",LMoptions[i],(int)tw->slc[i]);
  332. #endif
  333.                                     }
  334.                                 opts_debug_print(munger);
  335.                                 netwrite(tw->port,tw->parsedat,3);
  336.                                 }
  337.     
  338.                             opts_debug_print("SENT: IAC SE");
  339.                             sprintf((char *)tw->parsedat,"%c%c",IAC,TEL_SE);
  340.                             netwrite(tw->port,tw->parsedat,2);
  341.                             }
  342.                         else {
  343.                             sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_WONTTEL,*st++);
  344.                             opts_debug_print("SENT: WONT Linemode");
  345.                             netwrite(tw->port,tw->parsedat,3);
  346.                             }
  347.                         break;
  348.  
  349.                     case N_AUTHENTICATION:        /* do auth */
  350.                         if (!tw->myopts[OPT_AUTHENTICATION-MHOPTS_BASE]) {
  351.                             if (tw->authenticate) {
  352.                                 (tw->myopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
  353.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_WILLTEL,*st);
  354.                                 netwrite(tw->port,tw->parsedat,3);
  355. #ifdef OPTS_DEBUG
  356.                                 sprintf(munger,"SENT: WILL %s",teloptions[*st]);
  357.                                 opts_debug_print(munger); 
  358. #endif
  359.                             } else {
  360.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_WONTTEL,*st);
  361.                                 netwrite(tw->port,tw->parsedat,3);
  362. #ifdef OPTS_DEBUG
  363.                                 sprintf(munger,"SENT: WONT %s",teloptions[*st]);
  364.                                 opts_debug_print(munger); 
  365. #endif
  366.                             }
  367.                         }
  368.                         tw->telstate = STNORM;
  369.                         orig = ++st;
  370.                         break;
  371.  
  372.                     case N_ENCRYPT:             /* do encrypt */
  373.                         if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) {
  374.                             if (tw->encrypt) {
  375.                                 (tw->myopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
  376.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_WILLTEL,*st);
  377.                                 netwrite(tw->port,tw->parsedat,3);
  378. #ifdef OPTS_DEBUG
  379.                                 sprintf(munger,"SENT: WILL %s",teloptions[*st]);
  380.                                 opts_debug_print(munger); 
  381. #endif
  382.                             } else {
  383.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_WONTTEL,*st);
  384.                                 netwrite(tw->port,tw->parsedat,3);
  385. #ifdef OPTS_DEBUG
  386.                                 sprintf(munger,"SENT: WONT %s",teloptions[*st]);
  387.                                 opts_debug_print(munger); 
  388. #endif
  389.                             }
  390.                         }
  391.                         tw->telstate = STNORM;
  392.                         orig = ++st;
  393.                         break;
  394.  
  395.                     default:                /* But, we won't do .... */
  396.                         sprintf((char *)tw->parsedat,"%c%c%c",255,TEL_WONTTEL,*st++);
  397.                         netwrite(tw->port,tw->parsedat,3);  
  398. #ifdef OPTS_DEBUG
  399.                         sprintf(munger,"SENT: WONT %s",teloptions[*(st-1)]);
  400.                         opts_debug_print(munger); 
  401. #endif
  402.                         break;
  403.                     }
  404.                 tw->telstate = STNORM;
  405.                 orig = st;
  406.                 break;
  407.  
  408.  
  409. /*------------------------------------------------------------------------------*
  410.  *     Negotiate DONTTEL:  sent by the server whenever it wants the client to      *
  411.  *    definitely NOT do an option.  Sent to prevent client from negotiating an    *
  412.  *    unsupported option                                                            *
  413.  *------------------------------------------------------------------------------*/
  414.             case TEL_DONTTEL:
  415. #ifdef OPTS_DEBUG
  416.                 sprintf(munger,"RECV: %s %s",telstates[tw->telstate-TEL_SE],teloptions[*st]);
  417.                 opts_debug_print(munger); 
  418. #endif
  419.                 tw->telstate = STNORM;
  420.                 switch (*st++) {
  421.                     case N_ENCRYPT:                    /* dont encrypt */
  422.                     case N_AUTHENTICATION:            /* dont authenticate */
  423.                         tw->myopts[*(st-1)-MHOPTS_BASE] = 0;
  424.                         sprintf((char *)tw->parsedat,"%c%c%c", IAC, TEL_WONTTEL, *(st-1));
  425.                         netpush(tw->port);
  426.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  427. #ifdef OPTS_DEBUG
  428.                         sprintf(munger,"SENT: WONT %s", teloptions[*(st-1)]);
  429.                         opts_debug_print(munger); 
  430. #endif    
  431.                         break;
  432.                 }
  433.                 orig = st;
  434.                 break;
  435.  
  436.  
  437. /*------------------------------------------------------------------------------*
  438.  *     Negotiate WILLTEL:  sent by the client to try and get the server to use an    *
  439.  *    option.  This tells the server that the client is requesting that an option *
  440.  *     be used                                                                        *
  441.  *------------------------------------------------------------------------------*/
  442.             case TEL_WILLTEL:
  443. #ifdef OPTS_DEBUG
  444.                 sprintf(munger,"RECV: %s %s",telstates[tw->telstate-TEL_SE],teloptions[*st]);
  445.                 opts_debug_print(munger); 
  446. #endif
  447.                 tw->telstate = STNORM;
  448.                 switch(*st++) 
  449.                     {
  450.                     case N_ECHO:             /* Echo on the other end*/
  451. #ifdef    OPTS_DEBUG
  452.                         if (!tw->echo)
  453.                             opts_debug_print("tw->echo is False.");
  454. #endif
  455.                         if (!tw->echo)
  456.                             break;
  457.                         tw->echo = 0;    /* Ok, in that case they can echo... */
  458.                         changeport(scrn,scrn);
  459.                         sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DOTEL,1);
  460.                         netpush(tw->port);
  461.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  462. #ifdef OPTS_DEBUG
  463.                         sprintf(munger,"SENT: DO %s",teloptions[*(st-1)]);
  464.                         opts_debug_print(munger); 
  465. #endif
  466.                         break;
  467.                     
  468.                     case N_SGA:                /* Supress GA */
  469. #ifdef    OPTS_DEBUG
  470.                         if (tw->Usga)
  471.                             opts_debug_print("tw->Usga is True.");
  472. #endif
  473.                         if (tw->Usga)
  474.                             break;
  475.                         tw->Usga = 1;    /* Go Ahead and supress GA */
  476.                         sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DOTEL,3);
  477.                         netpush(tw->port);
  478.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  479. #ifdef OPTS_DEBUG
  480.                         sprintf(munger,"SENT: DO %s",teloptions[*(st-1)]);
  481.                         opts_debug_print(munger); 
  482. #endif
  483.                         break;
  484.                     
  485.                     case N_TIMING:                /* Timing Mark */
  486.                         tw->timing = 0;
  487.                         break;
  488.                     
  489.                     case N_AUTHENTICATION:        /* will auth */
  490.                         if (!tw->hisopts[OPT_AUTHENTICATION-MHOPTS_BASE]) {
  491.                             if (tw->authenticate) {
  492.                                 (tw->hisopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
  493.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DOTEL,OPT_AUTHENTICATION);
  494.                                 netwrite(tw->port,tw->parsedat,3);
  495. #ifdef OPTS_DEBUG
  496.                                 sprintf(munger,"SENT: WILL %s",teloptions[OPT_AUTHENTICATION]);
  497.                                 opts_debug_print(munger); 
  498. #endif
  499.                             } else {
  500.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DONTTEL,OPT_AUTHENTICATION);
  501.                                 netwrite(tw->port,tw->parsedat,3);
  502. #ifdef OPTS_DEBUG
  503.                                 sprintf(munger,"SENT: WONT %s",teloptions[OPT_AUTHENTICATION]);
  504.                                 opts_debug_print(munger); 
  505. #endif
  506.                             }
  507.                         }
  508.                         break;
  509.  
  510.                     case N_ENCRYPT:             /* will encrypt */
  511.                         if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE]) {
  512.                             if (tw->encrypt) {
  513.                                 (tw->hisopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
  514.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DOTEL,OPT_ENCRYPT);
  515.                                 netwrite(tw->port,tw->parsedat,3);
  516. #ifdef OPTS_DEBUG
  517.                                 sprintf(munger,"SENT: DO %s",teloptions[OPT_ENCRYPT]);
  518.                                 opts_debug_print(munger); 
  519. #endif
  520.                             } else {
  521.                                 sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DONTTEL,OPT_ENCRYPT);
  522.                                 netwrite(tw->port,tw->parsedat,3);
  523. #ifdef OPTS_DEBUG
  524.                                 sprintf(munger,"SENT: DONT %s",teloptions[OPT_ENCRYPT]);
  525.                                 opts_debug_print(munger); 
  526. #endif
  527.                             }
  528.                         }
  529.  
  530.                         if (tw->authenticate && tw->encrypt)    /* do this here (and tn3270?) ddd */
  531.                             encrypt_send_support(tw->edata);
  532.                         break;
  533.  
  534.                     default:
  535.                         sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DONTTEL,*(st-1));
  536.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  537. #ifdef OPTS_DEBUG
  538.                         sprintf(munger,"SENT: DONT %s",teloptions[*(st-1)]);
  539.                         opts_debug_print(munger); 
  540. #endif
  541.                     }
  542.                 orig = st;
  543.                 break;
  544.  
  545.  
  546.  
  547. /*------------------------------------------------------------------------------*
  548.  *     Negotiate WONTTEL:  The client refuses a Telnet option, and wants the         *
  549.  *    to forget about trying to negotiate it.                                        *
  550.  *------------------------------------------------------------------------------*/
  551.             case TEL_WONTTEL:
  552. #ifdef OPTS_DEBUG
  553.                 sprintf(munger,"?SENT: (WONTTEL)%s %s",telstates[tw->telstate-TEL_SE],teloptions[*st]);
  554.                 opts_debug_print(munger); 
  555. #endif
  556.                 tw->telstate = STNORM;
  557.                 switch(*st++) 
  558.                     {         /* which option? */
  559.                     case N_ECHO:             /* echo */
  560.                         if (tw->echo)
  561.                             break;
  562.                         tw->echo = 1;    /* Ok, I will echo if I have to... */
  563.                         changeport(scrn,scrn);
  564.                         sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DONTTEL,N_ECHO);
  565.                         netpush(tw->port);
  566.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  567. #ifdef OPTS_DEBUG
  568.                         sprintf(munger,"SENT: %s %s",telstates[TEL_WONTTEL-TEL_SE],teloptions[*(st-1)]);
  569.                         opts_debug_print(munger); 
  570. #endif    
  571.                         break;
  572.                     
  573.                     case N_SGA:
  574.                         if (!tw->Usga)
  575.                             break;
  576.                         tw->Usga = 0;
  577.                         sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DONTTEL,N_SGA);
  578.                         netpush(tw->port);
  579.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  580. #ifdef OPTS_DEBUG
  581.                         sprintf(munger,"SENT: %s %s",telstates[TEL_WONTTEL-TEL_SE],teloptions[*(st-1)]);
  582.                         opts_debug_print(munger); 
  583. #endif    
  584.                         break;
  585.                     
  586.                     case N_TIMING:                /* Timing Mark */
  587.                         tw->timing = 0;
  588.                         break;
  589.                     
  590.                     case N_ENCRYPT:                    /* wont encrypt */
  591.                     case N_AUTHENTICATION:            /* wont authenticate */
  592.                         tw->hisopts[*(st-1)-MHOPTS_BASE] = 0;
  593.                         sprintf((char *)tw->parsedat,"%c%c%c",IAC,TEL_DONTTEL,*(st-1));
  594.                         netpush(tw->port);
  595.                         netwrite(tw->port,tw->parsedat,3);  /* refuse it */
  596. #ifdef OPTS_DEBUG
  597.                         sprintf(munger,"SENT: WONT %s", teloptions[*(st-1)]);
  598.                         opts_debug_print(munger); 
  599. #endif    
  600.                         break;
  601.  
  602.                     default:
  603.                         break;
  604.                     }
  605.                 orig = st;
  606.                 break;
  607.  
  608.  
  609.  
  610. /*------------------------------------------------------------------------------*
  611.  *     SUBNEGOTIATION -- If there is an SB token found, then Telnet needs to do     *
  612.  *    some subnegotiating.  The subnegotiation data follows, and needs to be put    *
  613.  *    somewhere safe.  Make sure and update the state, so that we know that        *
  614.  *    Telnet is doing some subnegotiations and not just horsing around            *
  615.  *------------------------------------------------------------------------------*/
  616.             case TEL_SB:
  617.                 tw->telstate = NEGOTIATE;        /* Guess what I'm doing... */
  618.                 orig=st;
  619.                 substate=0;                /* Defined for each */
  620.                 tw->parseIndex =0;        /* No data yet! Clear any possible garbage */
  621.                 break;
  622.  
  623.             case NEGOTIATE:
  624.                 if (substate <200) {
  625.                     switch( *st) {
  626.                         case IAC:                /* is it the famous DOUBLE-IAC??? */
  627.                             if (*(st+1) ==IAC)     /* Yes, treat as data value 255 */
  628.                                 {
  629.                                 tw->parsedat[tw->parseIndex++]=*st++;
  630.                                 /*tw->parsedat[tw->parseIndex++]=* */ st++;
  631.                                 }
  632.                             else                 /* otherwise just save it */
  633.                                 {
  634.                                 tw->parsedat[tw->parseIndex]='\0';
  635.                                 substate=*st++;
  636.                                 }                            
  637.                             break;
  638.                         default:
  639.                             tw->parsedat[tw->parseIndex++]=*st++;
  640.                             break;
  641.                         }
  642.                     } else 
  643.                     
  644.                     {
  645.                     switch( substate)     /* subnegotiate */
  646.                         {
  647.                         case IAC:
  648.                             substate=*st++;
  649.                             if (substate==TEL_SE) {
  650.                                 switch( tw->parsedat[0]) 
  651.                                     {
  652. /*------------------------------------------------------------------------------*
  653.  *     SUBNegotiate Termtype:  send the term type data now                            *
  654.  *------------------------------------------------------------------------------*/
  655.                                     case N_TERMTYP:            
  656.                                         if (tw->parsedat[1]==1) 
  657.                                             {
  658.                                             char s[255], termtmp[40];
  659.                                             BlockMove(tw->answerback, termtmp, 32);
  660.                                             PtoCstr((StringPtr)termtmp);
  661.     #ifdef OPTS_DEBUG
  662.                                             sprintf(munger,"RECV: SB TERMINAL-TYPE SEND\r\nSEND: SB TERMINAL-TYPE IS %s\r\n",termtmp);
  663.                                             opts_debug_print(munger); 
  664.     #endif
  665.                                             netpush(tw->port);
  666.                                             netwrite(tw->port,"\377\372\030\000",4);
  667.                                             netpush(tw->port);
  668.                                             sprintf(s,"%s\377\360",termtmp);
  669.                                             netwrite(tw->port, s, strlen(s));
  670.                                             }
  671.                                         break;
  672.                                         
  673. /*------------------------------------------------------------------------------*
  674.  *     SUBNegotiate ENCRYPTION:                                                     *
  675.  *------------------------------------------------------------------------------*/
  676.                                     case N_ENCRYPT:    {
  677.                                         unsigned char *subpointer = &tw->parsedat[SB_TYPE];
  678.                                         long    sublen = &tw->parsedat[tw->parseIndex] - 
  679.                                             subpointer;
  680. #ifdef OPTS_DEBUG
  681.                                         {
  682.                                             short    j;
  683.                                             char *cp = munger;
  684.  
  685.                                             sprintf(cp,"RECV: SB ENCRYPT %02X ",
  686.                                                     tw->parsedat[SB_SUBOPTION]);
  687.                                             cp += strlen(cp);
  688.                                             for (j = 0; j < sublen; j++) {
  689.                                                 sprintf(cp, "%02X ", subpointer[j] & 0xff);
  690.                                                 cp += strlen(cp);
  691.                                             }
  692.                                             sprintf(cp, "\r\n");
  693.                                             opts_debug_print(munger); 
  694.                                         }
  695. #endif
  696.                                          if (tw->edata != NULL)
  697.                                             netportencryptstate(tw->port, (Ptr)tw->edata);
  698.                                         switch (tw->parsedat[SB_SUBOPTION]) {
  699.                                         case ENCRYPT_START:
  700.                                             if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE])     /* my_want_state_is_dont(tw->o_encrypt) */
  701.                                                 break;
  702.                                             encrypt_start(tw->edata, subpointer, sublen);
  703.                                             /*
  704.                                              * If we turned on decryption we must
  705.                                              * decrypt the remainder of the buffer
  706.                                              */
  707.                                             if (tw->edata->decrypt_input) {
  708.                                                 unsigned char *cp = st;
  709.                                                 while (cp < mark) {
  710.                                                     *cp = (*tw->edata->decrypt_input)(tw->edata, (int)(*cp));
  711.                                                     cp++;
  712.                                                 }
  713.                                                  netportencryptstate(tw->port, (Ptr)tw->edata);
  714.                                             }
  715.                                             break;
  716.  
  717.                                         case ENCRYPT_END:
  718.                                             if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_dont(tw->o_encrypt) */
  719.                                             break;
  720.                                             encrypt_end(tw->edata);
  721.                                             break;
  722.  
  723.                                         case ENCRYPT_SUPPORT:
  724.                                             if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_wont(tw->o_encrypt) */
  725.                                                 break;
  726.                                             encrypt_support(tw->edata, subpointer, sublen);
  727.                                             break;
  728.  
  729.                                         case ENCRYPT_REQSTART:
  730.                                         if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_wont(tw->o_encrypt) */
  731.                                             break;
  732.                                             encrypt_request_start(tw->edata, subpointer, sublen);
  733.                                             break;
  734.  
  735.                                         case ENCRYPT_REQEND:
  736.                                             if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_wont(tw->o_encrypt) */
  737.                                                 break;
  738.                                             /*
  739.                                              * We can always send an REQEND so that 
  740.                                              * we cannot get stuck encrypting.  We 
  741.                                              * should only get this if we have been 
  742.                                              * able to get in the correct mode
  743.                                              * anyhow.
  744.                                              */
  745.                                             encrypt_request_end(tw->edata);
  746.                                             break;
  747.                                         case ENCRYPT_IS:
  748.                                             if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_dont(tw->o_encrypt) */
  749.                                                 break;
  750.                                             encrypt_is(tw->edata, subpointer, sublen);
  751.                                             break;
  752.                                         case ENCRYPT_REPLY:
  753.                                             if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_wont(tw->o_encrypt) */
  754.                                                 break;
  755.                                             encrypt_reply(tw->edata, subpointer, sublen);
  756.                                             break;
  757.                                         case ENCRYPT_ENC_KEYID:
  758.                                             if (!tw->hisopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_dont(tw->o_encrypt) */
  759.                                                 break;
  760.                                             encrypt_enc_keyid(tw->edata, subpointer, sublen);
  761.                                             break;
  762.                                         case ENCRYPT_DEC_KEYID:
  763.                                             if (!tw->myopts[OPT_ENCRYPT-MHOPTS_BASE]) /* if my_want_state_is_wont(tw->o_encrypt) */
  764.                                                 break;
  765.                                             encrypt_dec_keyid(tw->edata, subpointer, sublen);
  766.                                             break;
  767.                                         default:
  768.                                             break;
  769.                                         }
  770.                                     }
  771.                                     break;
  772.  
  773. /*------------------------------------------------------------------------------*
  774.  *     SUBNegotiate Authentication:  send the authentication data now                 *
  775.  *------------------------------------------------------------------------------*/
  776.                                     case N_AUTHENTICATION:            
  777. #ifdef OPTS_DEBUG2
  778.                                         {
  779.                                             short    j;
  780.                                             char    *cp = munger;
  781.                                             char    *subpointer = &tw->parsedat[SB_TYPE];
  782.                                             long    sublen = &tw->parsedat[tw->parseIndex] - 
  783.                                                 subpointer;
  784.  
  785.                                             sprintf(cp,"RECV: SB AUTH %02X ",
  786.                                                     tw->parsedat[SB_SUBOPTION]);
  787.                                             cp += strlen(cp);
  788.                                             for (j = 0; j < sublen; j++) {
  789.                                                 sprintf(cp, "%02X ", subpointer[j] & 0xff);
  790.                                                 cp += strlen(cp);
  791.                                             }
  792.                                             sprintf(cp, "\r\n");
  793.                                             opts_debug_print(munger); 
  794.                                         }
  795. #endif
  796.                                         switch (tw->parsedat[SB_SUBOPTION]) {
  797.                                         case TNQ_IS:
  798.                                             break;
  799.  
  800.                                         case TNQ_SEND:
  801.                                             /*
  802.                                              * For telnet clients.
  803.                                              * The buffer contains:
  804.                                              * AUTHENTICATION SEND type modifier 
  805.                                              *        [type modifier] [...]
  806.                                              * Scan the type/modifier pairs until we 
  807.                                              * find one we can do. Since they are are 
  808.                                              * in priority order, the  first one we
  809.                                              * find that we can do wins.
  810.                                              */
  811.                                             cp = &tw->parsedat[SB_TYPE];
  812.                                             for (; cp < &tw->parsedat[tw->parseIndex]; 
  813.                                                                     cp += 2) {
  814.                                                 switch (*cp) {
  815.                                                 case AUTH_KERBEROS_V4:
  816.                                                     if (krb_telnet(tw, (char *)cp, true)) {
  817.                                                         /*
  818.                                                          * if krb_telnet fails, send null authentication
  819.                                                          * to avoid hanging.
  820.                                                          */
  821.                                                         tn_sendsub(tw, N_AUTHENTICATION, TNQ_IS, 
  822.                                                                        nullbuf, sizeof(nullbuf));
  823.                                                     }                                                                        
  824.                                                     goto xx1;
  825.                                                 }
  826.                                             }
  827.                                             /*
  828.                                              * If we can't do any of the requested 
  829.                                              * authorizations, send AUTH_NULL.
  830.                                              */
  831.                                             tn_sendsub(tw, N_AUTHENTICATION, TNQ_IS, 
  832.                                                        nullbuf, sizeof(nullbuf));
  833.                                             xx1:
  834.                                             break;
  835.  
  836.                                         case TNQ_REPLY:
  837.                                             /*
  838.                                              * This is a reply to information we sent 
  839.                                              * in a previous IS AUTH or CHALLENGE 
  840.                                              * command. The buffer contains:
  841.                                              * AUTHENTICATION REPLY type modifier 
  842.                                              *       auth-data-type [auth data bytes]
  843.                                              */
  844.                                             switch (tw->parsedat[SB_TYPE] & 0xFF) {
  845.                                             case AUTH_KERBEROS_V4:
  846.                                                 tn_kerberos_reply(tw, (unsigned char *)tw->parsedat);
  847.                                                 break;
  848.                                             default:
  849.                                                 ;
  850.                                                 /* should we do somthing with an 
  851.                                                    unknown reply type ddd */
  852.                                             }
  853.                                             break;
  854.  
  855.                                         case TNQ_NAME:
  856.                                             /*
  857.                                              * For the telnet server. This is the 
  858.                                              * name that the telnet client
  859.                                              * wants us to use.
  860.                                              */
  861.                                             break;
  862.                                         } /* switch tw->parsedat[SB_SUBOPTION] */
  863.                                         break;
  864.                                         
  865. /*------------------------------------------------------------------------------*
  866.  *     SUBNegotiate Linemode:  set up local characters, modes, and such            *
  867.  *------------------------------------------------------------------------------*/
  868.                                     case N_LINEMODE:
  869.                                         switch(tw->parsedat[1])
  870.                                             {
  871.                                             char s[80];
  872.  
  873.                                             case L_MODE:    /* change mode */
  874. #ifdef OPTS_DEBUG
  875.                                                 strcpy(s, "RECV: SB LINEMODE MODE => ");
  876.                                                 DemangleLineModeShort(s, tw->parsedat[2]);
  877.                                                 opts_debug_print(s);
  878. #endif
  879.                                                 if (tw->lineAllow) {            // First make sure we allowed linemode in the first place.
  880.                                                     // RFC 1184 says client should ignore MODE negotiations with the MODE_ACK bit set, and should not
  881.                                                     //    generate a response if the negotiated MODE matches the current MODE
  882.                                                     if (!((tw->parsedat[2] & L_MODE_ACK) || ((tw->parsedat[2] & L_MODE_MASK) == tw->lmode))) {
  883.                                                     
  884.                                                         // This is a hack.  Accept the state of L_EDIT and L_TRAPSIG that the server wants.  If
  885.                                                         // the server only wants zero, one, two or both of those bits, generate an ack.  Otherwise
  886.                                                         // send the server a mode that masks out all requested bits except EDIT and TRAPSIG.
  887.                                                         
  888.                                                         // (Now, since we only support L_EDIT and/or L_TRAPSIG, if those are the only modes requested,)
  889.                                                         //    (send an ACK of that MODE to the server.)
  890.                                                         
  891.                                                         tw->lmode = (tw->parsedat[2] & (L_EDIT | L_TRAPSIG));    // Accept the mode.
  892.                                                         
  893.                                                         if ((tw->parsedat[2] & (L_EDIT | L_TRAPSIG)) == tw->parsedat[2]) {
  894.                                                             tw->parsedat[2] |= L_MODE_ACK;    // Set the MODE_ACK bit
  895.                                                             }
  896.                                                         // We got a MODE bit we dont support, mask out just what we support and send it back, UNacked.
  897.                                                         else {
  898.                                                             tw->parsedat[2] = tw->parsedat[2] & (L_EDIT | L_TRAPSIG);
  899.                                                             }
  900.  
  901.                                                         sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_MODE);
  902.                                                         netwrite(tw->port,s,4);
  903.                                                         sprintf(s,"%c%c%c",tw->parsedat[2],IAC,TEL_SE);
  904.                                                         netwrite(tw->port,s,3); 
  905. #ifdef OPTS_DEBUG
  906.                                                         opts_debug_print("SENT: IAC SB");
  907.                                                         strcpy(s, "SENT: LM MODE = ");
  908.                                                         DemangleLineModeShort(s, tw->parsedat[2]);
  909.                                                         opts_debug_print(s);
  910.                                                         opts_debug_print("SENT: IAC SE");
  911. #endif
  912.                                                     }
  913. #ifdef OPTS_DEBUG
  914.                                                     else {
  915.                                                         strcpy(s, "LINEMODE MODE = ");
  916.                                                         DemangleLineModeShort(s, tw->parsedat[2]);
  917.                                                         opts_debug_print(s);
  918.                                                         if (tw->parsedat[2] & L_MODE_ACK) 
  919.                                                             opts_debug_print("\tignored 'cause MODE_ACK was set.");
  920.                                                         else
  921.                                                             opts_debug_print("\tIMPLICITLY ACCEPTED.");
  922.                                                         strcpy(s, "Curr Linemode = ");
  923.                                                         DemangleLineModeShort(s, tw->lmode);
  924.                                                         opts_debug_print(s);
  925.                                                     }
  926. #endif
  927.                                                     
  928.                                                 }
  929.                                                 break;
  930.                                             
  931.                                             case TEL_DOTEL:    
  932. #ifdef OPTS_DEBUG
  933.                                                 sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
  934.                                                 opts_debug_print(munger);
  935. #endif
  936.                                                 netwrite(tw->port,"\377\372\042",3);
  937.                                                 sprintf(s,"%c\002\377\360",TEL_WONTTEL);
  938.                                                 opts_debug_print("SENT: IAC SB LINEMODE WONT FORWARDMASK IAC SE");
  939.                                                 netwrite(tw->port,s,strlen(s));
  940.                                                 break;
  941.  
  942.                                             case TEL_WILLTEL:
  943. #ifdef OPTS_DEBUG
  944.                                                 sprintf(munger,"RECV: SB LINEMODE WILL %c", tw->parsedat[2]);
  945.                                                 opts_debug_print(munger);
  946. #endif
  947.                                                 netwrite(tw->port,"\377\372\042",3);
  948.                                                 sprintf(s,"%c\002\377\360",TEL_DONTTEL);
  949.                                                 opts_debug_print("SENT: IAC SB LINEMODE DONT FORWARDMASK IAC SE");
  950.                                                 netwrite(tw->port,s,strlen(s));
  951.                                                 break;
  952.  
  953.  
  954.                                             case L_SLC:        /* set local chars */
  955.                                                 {
  956.                                                 short    lmslcflag = 0;
  957. #ifdef OPTS_DEBUG
  958.                                                 sprintf(munger,"RECV: SB LINEMODE SLC");
  959.                                                 opts_debug_print(munger);
  960.                                                 for(i=2;(tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
  961.                                                     if(tw->parsedat[i+1] & SLC_AWK)
  962.                                                         sprintf(munger,"     %s %s|AWK %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
  963.                                                     else
  964.                                                         sprintf(munger,"     %s %s %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
  965.                                                     opts_debug_print(munger);
  966.                                         // 2.6b16.1            if ((unsigned char)(tw->parsedat[i+2])==IAC) i++;
  967.                                                     }    /* end for */
  968. #endif
  969.  
  970.                                                 for (i=2, lmslcflag=0; (tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
  971.  
  972.                                                     // If func = 0, skip it 'cause we are the client.
  973. //                                                    if (tw->parsedat[i] == 0)
  974. //                                                        continue;
  975.                                                     
  976.                                                     // If it's a function we don't know about, say we don't support it.  If the server is telling
  977.                                                     // us he doesn't support it, just ignore him.
  978.                                                     if (tw->parsedat[i] > SLC_MAX) {
  979.                                                         if ((tw->parsedat[i+1] & SLC_LEVELBITS) != SLC_NOSUPPORT) {
  980.                                                             if (!lmslcflag) {
  981.                                                                 lmslcflag = 1;        // Do this only once
  982.                                                                 sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  983.                                                                 netwrite(tw->port,s,4);
  984.                                                                 opts_debug_print("SENT: IAC SB LINEMODE SLC");
  985.                                                                 }
  986.                                                             sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
  987. #ifdef OPTS_DEBUG
  988.                                                             sprintf(munger,"     %d SLC_NOSUPPORT 0",tw->parsedat[i]);
  989.                                                             opts_debug_print(munger);
  990. #endif
  991.                                                             netwrite(tw->port,s,3);
  992.                                                         }
  993.                                                         else
  994.                                                             continue;
  995.                                                     }
  996.                                                     
  997.                                                     // RFC 1184: If we get a response that is the same as the current setting, ignore it.  Technically, we
  998.                                                     //    should check the value for a CANTCHANGE response to satisfy part 2 of Sec 5.5.  However, since we
  999.                                                     //    advertised that key as CANTCHANGE in the first place, the server should not be changing it.  This
  1000.                                                     //    should be fixed later, however I don't see it causing big problems right now. - JMB 12/93
  1001.                                                     
  1002.                                                     if (! ((((tw->parsedat[i+1] & SLC_LEVELBITS) == SLC_NOSUPPORT) && (tw->slc[tw->parsedat[i]] == -1))
  1003.                                                         || (((tw->parsedat[i+1] & SLC_LEVELBITS) == SLC_CANTCHANGE) && (tw->slc[tw->parsedat[i]] != -1)))) {
  1004.                                                         // If we get to this point, the value sent to us doesn't agree with what we want.
  1005.                                                         
  1006.                                                             
  1007.                                                         if (!(tw->parsedat[i+1] & SLC_AWK)) {
  1008.                                                             if (!lmslcflag) {
  1009.                                                                 lmslcflag = 1;        // Do this only once
  1010.                                                                 sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  1011.                                                                 netwrite(tw->port,s,4);
  1012.                                                                 opts_debug_print("SENT: IAC SB LINEMODE SLC");
  1013.                                                                 }
  1014.                                                         
  1015.                                                             if (tw->slc[tw->parsedat[i]]==-1)
  1016.                                                                 {
  1017.                                                                 sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
  1018. #ifdef OPTS_DEBUG
  1019.                                                                 sprintf(munger,"     %s SLC_NOSUPPORT 0",LMoptions[tw->parsedat[i]]);
  1020. #endif
  1021.                                                                 }
  1022.                                                             else
  1023.                                                                 {
  1024.                                                                 sprintf(s,"%c%c%c",tw->parsedat[i],SLC_CANTCHANGE,(char)tw->slc[tw->parsedat[i]]);
  1025. #ifdef OPTS_DEBUG
  1026.                                                                 sprintf(munger,"     %s SLC_CANTCHANGE %d",LMoptions[tw->parsedat[i]],
  1027.                                                                                             (char)tw->slc[tw->parsedat[i]]);
  1028. #endif
  1029.                                                                 }                                                                
  1030. #ifdef OPTS_DEBUG
  1031.                                                             opts_debug_print(munger);
  1032. #endif
  1033.                                                             netwrite(tw->port,s,3);
  1034.                                         // 2.6b16.1                    if (tw->parsedat[i+2]==IAC) i++;
  1035.                                                             }
  1036.                                                         }
  1037.                                                     }
  1038.                                                     
  1039.                                                 if (lmslcflag) {
  1040.                                                     sprintf(s,"%c%c",IAC,TEL_SE);
  1041.                                                     netwrite(tw->port,s,2);
  1042.                                                     }
  1043.                                                     
  1044.  
  1045.                                                     /* otherwise just exit */
  1046.                                                     }
  1047.                                                     break;
  1048.                                                 
  1049.                                                 default:
  1050. #ifdef OPTS_DEBUG
  1051.                                                     sprintf(munger, "RECV: SB LINEMODE ?? (?? = %c)", tw->parsedat[1]);
  1052.                                                     opts_debug_print(munger);
  1053. #endif
  1054.                                                     break;
  1055.  
  1056.                                                 }
  1057.                                         break;
  1058.  
  1059. /* end of all the new line-mode stuff */                                
  1060.                                 
  1061.                                 
  1062.                                 default:
  1063.                                     break;
  1064.                                 }
  1065.                             } // substate == TEL_SE
  1066.                             orig=st;
  1067.                             tw->telstate=STNORM;
  1068.                             break;
  1069.                         default:
  1070.                             orig=st;
  1071.                             tw->telstate=STNORM;
  1072.                             break;
  1073.                         } // switch(substate)
  1074.                     }
  1075.  
  1076.                 break;
  1077.             default:
  1078.                 tw->telstate = STNORM;
  1079.                 break;
  1080.         } // switch(tw->telstate)
  1081.  
  1082. /*
  1083. * quick scan of the remaining string, skip chars while they are
  1084. * uninteresting
  1085. */
  1086.         if (tw->telstate == STNORM) {
  1087. /*
  1088. *  skip along as fast as possible until an interesting character is found
  1089. */
  1090.  
  1091.             if (!tw->eightbit) {                                            /* BYU 2.4.10 */
  1092.                 while (st < mark) {                                            /* BYU 2.4.10 */
  1093.                     if (*st == IAC)                                         /* BYU 2.4.10 */
  1094.                         break;                                                /* BYU 2.4.10 */
  1095.                     else {                                                    /* BYU 2.4.10 */
  1096.                         *st &= 0x7f;                                         /* BYU 2.4.10 */
  1097.                         if (*st == ESC  || *st == GS)                         /* BYU 2.4.10 */
  1098.                             break;                                            /* BYU 2.4.10 */
  1099.                         st++;                                                /* BYU 2.4.10 */
  1100.                 }    }                                                        /* BYU 2.4.10 */
  1101.             } else                                                             /* BYU 2.4.10 */
  1102.                 while (st < mark && *st != ESC  && *st < 255 && *st != GS)     // MP: translation mod
  1103.                     st++;                                                     /* BYU 2.4.10 */
  1104. /*
  1105. *  send the string where it belongs
  1106. */
  1107.             if (!tw->timing) {
  1108.                 if (tw->termstate == TEKTYPE) {
  1109.                     short i;
  1110.                     
  1111.                     i = VGwrite( tw->curgraph,(char *) orig,  st-orig);    /* BYU LSC */
  1112.                     if (i < (st - orig)) {
  1113.                         detachGraphics(tw->curgraph);
  1114.                         st = orig + i;
  1115.                         }
  1116.                     }
  1117.                 else if (tw->termstate == RASTYPE) {
  1118.                     short i;
  1119.                     
  1120.                     i= VRwrite((char *) orig, st-orig);        /* BYU LSC */
  1121.                     if (i <(st-orig)) {
  1122.                         tw->termstate = VTEKTYPE;
  1123.                         st = orig +i;                /* Next char to parse */
  1124.                         }
  1125.                     }
  1126.                 else 
  1127.                     VSwrite( tw->vs,(char *) orig,st-orig);    /* BYU LSC - send to virtual VT102 */
  1128.                 }
  1129.  
  1130.             orig = st;                /* forget what we have sent already */
  1131.  
  1132.             if (st < mark)
  1133.                 switch (*st) {
  1134.                     case 255:            /* telnet IAC */
  1135.                         tw->telstate = IACFOUND;
  1136.                         st++;
  1137.                         break;
  1138.                     case GS:
  1139.                         if (tw->telstate != GS) {
  1140.                             tw->telstate = GS;
  1141.                             }
  1142.                         else
  1143.                             tw->telstate = STNORM;
  1144.                         st++;
  1145.                         break;
  1146.                         
  1147.                     case ESC:            /* ESCape code */
  1148.                         if (st == mark-1 || *(st+1) == 12 || *(st+1) == '^' ) {
  1149.                             tw->telstate = ESCFOUND;
  1150.                         }
  1151.                         st++;            /* strip or accept ESC char */
  1152.                         break;
  1153.     
  1154.                     default:
  1155.                         if (*st++ > 127) {
  1156.                             if (st==mark)                            /*new addition */
  1157.                                 VSwrite(tw->vs,(char *) orig,1);    /* BYU LSC */
  1158.                              }
  1159.                         break;
  1160.                 }    // switch(*st)
  1161.             } // tw->telstate == STNORM
  1162.     } // while (st < mark)
  1163.     } // tw->termstate != DUMBTYPE
  1164. } /* parse */
  1165.  
  1166. void    SendNAWSinfo(WindRec *s, short horiz, short vert)
  1167. {
  1168.     char            blah[20];
  1169.     unsigned char    height, width;
  1170.  
  1171.     height = vert & 0xff;
  1172.     width = horiz & 0xff;
  1173.     
  1174.     /* 931112, ragge, NADA, KTH, ugly patch to not send IAC as window size  */
  1175.     if(height == 0xFF) height = 0xFE;
  1176.     if(width == 0xFF) width = 0xFE;
  1177.  
  1178.     netpush (s->port);
  1179.  
  1180. /* NCSA: syntax for command is:  IAC SB NAWS widthHI widthLO heightHI heightLO IAC SE */
  1181.  
  1182.     netwrite(s->port,"\377\372\037\000",4);
  1183.     sprintf(blah,"%c\000", width);
  1184.     netwrite(s->port,blah,2);
  1185.     sprintf(blah,"%c\377\360", height);
  1186.     netwrite(s->port,blah,3);
  1187.     opts_debug_print("SENT: IAC SB NAWS <data> IAC SE");        
  1188. }
  1189.  
  1190. /*
  1191.  * Implementation specific Kerberos routines
  1192.  */
  1193.  
  1194.  
  1195. /*
  1196.  * net_write
  1197.  */
  1198. void net_write (struct WindRec *tw, char *buf, short length)
  1199. {
  1200.     netpush(tw->port);
  1201.     netwrite(tw->port, buf, length);
  1202. }
  1203.  
  1204.  
  1205. /*
  1206.  * send_auth_opt
  1207.  */
  1208. void send_auth_opt (struct WindRec *tw)
  1209. {
  1210.     unsigned char *cp, buf[30];
  1211.     
  1212.     cp = buf;
  1213.     if (tw->authenticate) {
  1214.         sprintf((char *)cp, "%c%c%c", IAC, TEL_WILLTEL, OPT_AUTHENTICATION);    /* will authenticate */
  1215.         cp += 3;
  1216.         (tw->myopts)[OPT_AUTHENTICATION-MHOPTS_BASE] = 1;
  1217.  
  1218.         if (tw->encrypt) {
  1219.             sprintf((char *)cp, "%c%c%c", IAC, TEL_WILLTEL, OPT_ENCRYPT);        /* will encrypt */
  1220.             cp += 3;
  1221.             (tw->myopts)[OPT_ENCRYPT-MHOPTS_BASE] = 1;
  1222.         }
  1223.         netpush(tw->port);
  1224.         netwrite(tw->port, buf, cp - buf);
  1225.     }
  1226. }
  1227.  
  1228.  
  1229. void tn_sendsub (struct WindRec *tw, short code, short request, char *cp, short length)
  1230. {
  1231.     long len;
  1232.     unsigned char *src, *lp, *limit;
  1233.     static char start[] = {IAC, TEL_SB, 0, 0};
  1234.     static char end[] = {IAC, TEL_SE};
  1235.  
  1236.     src = (unsigned char *)cp;
  1237.     limit = src + length;
  1238.     start[2] = code;
  1239.     start[3] = request;
  1240.     netpush(tw->port);
  1241.     netwrite(tw->port, start, 4);
  1242.  
  1243.     /*
  1244.      * Transmit the buffer. IACs must be doubled
  1245.      */
  1246.     if (*src == IAC) {                        /* check initial iac in buffer */
  1247.         netpush(tw->port);
  1248.         netwrite(tw->port, start, 1);        /* IAC */
  1249.     }
  1250.     while (src < limit) {
  1251.         lp = src+1;                            /* dont check first char */
  1252.         while (lp < limit) {                /* scan for IAC */
  1253.             if (*lp == IAC)
  1254.                 break;
  1255.             lp++;        
  1256.         }
  1257.         len = lp - src;
  1258.         if (lp < limit)                        /* if stopped on IAC */
  1259.             len++;                            /* include IAC in xmit */
  1260.  
  1261.         netpush(tw->port);
  1262.         netwrite(tw->port, src, len);
  1263.  
  1264.         src = lp;                            /* resume scanning */
  1265.     }
  1266.  
  1267.     netpush(tw->port);
  1268.     netwrite(tw->port, end, 2);
  1269. }
  1270.  
  1271.  
  1272. /*
  1273.  * getcname
  1274.  * Return a pointer to the cannonical host name
  1275.  */
  1276. char *getcname (WindRec *tw)
  1277. {
  1278.     char *cp;
  1279.     static char *b, buf[100];
  1280.  
  1281.     cp = 0;
  1282.     if (tw->cannon[0])
  1283.         cp = tw->cannon;
  1284.  
  1285. //    Doing the following is bad because we disposed of our init params!
  1286. //    else if ((*(*(ConnInitParams **)(tw->myInitParams))->session)->hostname)
  1287. //        cp = (char *)(*(*(ConnInitParams **)(tw->myInitParams))->session)->hostname;
  1288.  
  1289.     /* make a local copy to avoid locking handles */
  1290.     if (cp) {
  1291.         b = buf;        
  1292.         while (*cp)
  1293.             *b++ = *cp++;            
  1294.         *b++ = '\0';
  1295.         return buf;
  1296.     }
  1297.  
  1298.     return cp;
  1299. }
  1300.  
  1301.  
  1302. /*
  1303.  * encryptStatechange
  1304.  * Called by encrypt.c when the encryption state changes
  1305.  */
  1306. #define kOurHit    32
  1307. void encryptStatechange (struct WindRec *tw)
  1308. {
  1309.     MyWDEFPatch(zoomDocProc , tw->wind, wDraw, kOurHit);
  1310. }
  1311.  
  1312. void DemangleLineMode(char *s, short mode)
  1313. {
  1314. #ifdef OPTS_DEBUG
  1315.     short     i;
  1316.     
  1317.     for (i=0; i<5; i++) {
  1318.         if (mode & (1 << i))
  1319.             strcat(s, LMmodes[i]);
  1320.     }
  1321. #endif
  1322. }
  1323.  
  1324. void DemangleLineModeShort(char *s, short mode)
  1325. {
  1326. #ifdef OPTS_DEBUG
  1327.     short     i;
  1328.     
  1329.     for (i=0; i<5; i++) {
  1330.         if (mode & (1 << i))
  1331.             strcat(s, LMmodeBits[i]);
  1332.         else
  1333.             strcat(s," ");
  1334.     }
  1335. #endif
  1336. }
  1337.  
  1338. #if 0    // Temp storage space - JMB 2.6b16.1
  1339.                                                 /* First check to see if we need to reply */
  1340.                                                 for (i=2;(tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
  1341.                                                     if (!(tw->parsedat[i+1] & SLC_AWK)) break;
  1342.                                                     if ((unsigned char)(tw->parsedat[i+2])==IAC) i++;
  1343.                                                     }
  1344.  
  1345.                                                 /* if we do then send a reply */
  1346.                                                 if ((tw->parsedat[i]!=IAC) && (tw->parsedat[i]!='\0')) {
  1347.                                                 //    sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  1348.                                                 //    netwrite(tw->port,s,4);
  1349.                                                 //    opts_debug_print("SENT: IAC SB LINEMODE SLC");
  1350.     
  1351.  
  1352. #ifdef NEWSLC
  1353.                                                     for (i=2; (tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3)
  1354.                                                         {
  1355.                                                         if (!(tw->parsedat[i+1] & SLC_AWK))        /* no response of ACK set */
  1356.                                                             {
  1357.                                                             if (tw->parsedat[i+1] != SLC_NOSUPPORT)
  1358.                                                                 {
  1359.                                                                 sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
  1360. #ifdef OPTS_DEBUG
  1361.                                                                 sprintf(munger,"     %s NOSUPPORT 0",LMoptions[tw->parsedat[i]]);
  1362. #endif
  1363.                                                                 }
  1364.                                                             else        /* Acknowledge the No_Support case */
  1365.                                                                 {
  1366.                                                                 sprintf(s,"%c%c%c",tw->parsedat[i],SLC_AWK|SLC_NOSUPPORT,(char)0);
  1367. #ifdef OPTS_DEBUG
  1368.                                                                 sprintf(munger,"     %s NOSUPPORT|AWK 0",LMoptions[tw->parsedat[i]]);
  1369. #endif
  1370.                                                                 }                                                                
  1371. #ifdef OPTS_DEBUG
  1372.                                                             opts_debug_print(munger);
  1373. #endif
  1374.                                                             netwrite(tw->port,s,3);
  1375.                                                             }
  1376.                                                             if ((unsigned char)(tw->parsedat[i+2])==IAC) i++;
  1377.                                                         }
  1378.  
  1379. #else
  1380.                                                     for (i=2, lmslcflag=0; (tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
  1381.                                                         // RFC 1184: If we get a response that is the same as the current setting, ignore it.  Technically, we
  1382.                                                         //    should check the value for a CANTCHANGE response to satisfy part 2 of Sec 5.5.  However, since we
  1383.                                                         //    advertised that key as CANTCHANGE in the first place, the server should not be changing it.  This
  1384.                                                         //    should be fixed later, however I don't see it causing big problems right now. - JMB 12/93
  1385.                                                         if (! ((((tw->parsedat[i+2] & SLC_LEVELBITS) == SLC_NOSUPPORT) && (tw->slc[tw->parsedat[i+1]] == -1))
  1386.                                                             || (((tw->parsedat[i+2] & SLC_LEVELBITS) == SLC_CANTCHANGE) && (tw->slc[tw->parsedat[i+1]] != -1)))) {
  1387.                                                             // If we get to this point, the value sent to us doesn't agree with what we want.
  1388.                                                             
  1389.                                                                 
  1390.                                                             if (!(tw->parsedat[i+1] & SLC_AWK)) {
  1391.                                                                 if (!lmslcflag) {
  1392.                                                                     lmslcflag = 1;        // Do this only once
  1393.                                                                     sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  1394.                                                                     netwrite(tw->port,s,4);
  1395.                                                                     opts_debug_print("SENT: IAC SB LINEMODE SLC");
  1396.                                                                     }
  1397.                                                             
  1398.                                                                 if (tw->slc[tw->parsedat[i]]==-1)
  1399.                                                                     {
  1400.                                                                     sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
  1401. #ifdef OPTS_DEBUG
  1402.                                                                     sprintf(munger,"     %s SLC_NOSUPPORT 0",LMoptions[tw->parsedat[i]]);
  1403. #endif
  1404.                                                                     }
  1405.                                                                 else
  1406.                                                                     {
  1407.                                                                     sprintf(s,"%c%c%c",tw->parsedat[i],SLC_CANTCHANGE,(char)tw->slc[tw->parsedat[i]]);
  1408. #ifdef OPTS_DEBUG
  1409.                                                                     sprintf(munger,"     %s SLC_CANTCHANGE %d",LMoptions[tw->parsedat[i]],
  1410.                                                                                                 (char)tw->slc[tw->parsedat[i]]);
  1411. #endif
  1412.                                                                     }                                                                
  1413. #ifdef OPTS_DEBUG
  1414.                                                                 opts_debug_print(munger);
  1415. #endif
  1416.                                                                 netwrite(tw->port,s,3);
  1417.                                                                 if (tw->parsedat[i+2]==IAC) i++;
  1418.                                                                 }
  1419.                                                             }
  1420.                                                         }
  1421.                                                         
  1422. #endif
  1423.                                                     if (lmslcflag) {
  1424.                                                         sprintf(s,"%c%c",IAC,TEL_SE);
  1425.                                                         netwrite(tw->port,s,2);
  1426.                                                         }
  1427.                                                     }
  1428.  
  1429.                                                     /* otherwise just exit */
  1430.                                                     }
  1431.                                                     break;
  1432. #endif